package echecs;

import echecs.Pieces.Piece;
import static echecs.Echiquier.Case.*;
import static echecs.Pieces.Piece.*;

public class Algorithme implements Echiquier {

    private boolean prise_en_passant;
    private Couleur _couleurQuiJoue;

    private void traiter_0() {
        int index_depart = 0;
        Piece _piece;
        while (index_depart < NB_COLONNES * NB_RANGEES) {
            _piece = PIECES[index_depart];
            if (_piece != null && _piece.getCouleur() == _couleurQuiJoue) {
                traiter_1(index_depart, _piece, 1, 0);
            }
            index_depart++;
        }
    }

    private void traiter_1(int pIndexDepart, Piece pPieceDepart, int pDistance, int pIndexDirection) {

        afficher(pIndexDepart, pPieceDepart);
        boolean pPrise = false;
        if (pPieceDepart.isMultiDepl()) {
            while (pIndexDirection < pPieceDepart.getDeplacement().length) {
                while (case_vide(pIndexDepart, pPieceDepart, pDistance, pIndexDirection)) {
                    traiter(pIndexDepart, pPieceDepart, pDistance, pIndexDirection, pPrise);
                    pDistance++;
                }
                if (case_nonvide(pIndexDepart, pPieceDepart, pDistance, pIndexDirection) &&
                        couleurs_opposees(pIndexDepart, pPieceDepart, pDistance, pIndexDirection)) {
                    traiter(pIndexDepart, pPieceDepart, pDistance, pIndexDirection, !pPrise);
                }
                pDistance = 1;
                pIndexDirection++;
            }
        } else if (pPieceDepart.estUnPion()) {
            traiter_pion(pIndexDepart, pPieceDepart);

        } else {
            pDistance = 1;
            while (pIndexDirection < pPieceDepart.getDeplacement().length) {
                if (case_vide(pIndexDepart, pPieceDepart, pDistance, pIndexDirection)) {
                    traiter(pIndexDepart, pPieceDepart, pDistance, pIndexDirection, pPrise);
                } else if (case_nonvide(pIndexDepart, pPieceDepart, pDistance, pIndexDirection) &&
                        couleurs_opposees(pIndexDepart, pPieceDepart, pDistance, pIndexDirection)) {
                    traiter(pIndexDepart, pPieceDepart, pDistance, pIndexDirection, !pPrise);
                }
                pIndexDirection++;
            }
        }
        System.out.println();
        pIndexDirection = 0;
    }

    private void placer(Piece pPiece, Case pCase) {
        PIECES[valeur(pCase)] = pPiece;
    }

    private void traiter_pion(int pIndexDepart, Piece pPieceDepart) {
        int pDistance = 1, pIndexDirection = 0;
        boolean pPrise = false;
        if (prise_en_passant) {
            traiter_ep();
        }
        if (!case_existe(pIndexDepart, pPieceDepart, pDistance, pIndexDirection)) {
            traiter_promotion();
        }
        if (case_vide(pIndexDepart, pPieceDepart, pDistance, pIndexDirection)) {
            traiter(pIndexDepart, pPieceDepart, pDistance, pIndexDirection, pPrise);
            if (estUnPionDepart(pIndexDepart, pPieceDepart)) {
                pDistance = 2;
                if (case_vide(pIndexDepart, pPieceDepart, pDistance, pIndexDirection)) {
                    traiter(pIndexDepart, pPieceDepart, pDistance, pIndexDirection, pPrise);
                }
            }
        }
        for (pIndexDirection = 1; pIndexDirection <= 2; pIndexDirection++) {
            if (case_nonvide(pIndexDepart, pPieceDepart, pDistance, pIndexDirection)) {
                if (couleurs_opposees(pIndexDepart, pPieceDepart, pDistance, pIndexDirection)) {
                    traiter(pIndexDepart, pPieceDepart, pDistance, pIndexDirection, !pPrise);
                }
            }
        }
    }

    private boolean roiEnEchec(int pIndexDepart, int pIndexArrivee) {
        Piece[] copyPIECES = new Piece[NB_COLONNES * NB_RANGEES];
        System.arraycopy(PIECES, 0, copyPIECES, 0, NB_COLONNES * NB_RANGEES);
        copyPIECES = simuler_coups(pIndexDepart, pIndexArrivee, copyPIECES);
        int index = 0;
        int index_roi = 0;
        Piece piece;
        while (index < NB_COLONNES * NB_RANGEES) {
            piece = PIECES[index];
            if (piece == ROI_BLANC && _couleurQuiJoue == Couleur.BLANC ||
                    piece == ROI_NOIR && _couleurQuiJoue == Couleur.NOIR) {
                index_roi = index;
            }
            index++;
        }
        System.out.print("-" + Case.valeur(index_roi) + "-");
        return false;
    }

    private Piece[] simuler_coups(int pIndexDepart, int pIndexArrivee, Piece[] pCopyPIECES) {
        pCopyPIECES[pIndexArrivee] = pCopyPIECES[pIndexDepart];
        pCopyPIECES[pIndexDepart] = null;
        return pCopyPIECES;
    }

    private void traiter(int pIndexDepart, Piece pPieceDepart, int pDistance, int pIndexDirection, boolean pPrise) {
//        roiEnEchec(pIndexDepart, index_arrivee(pIndexDepart, pPieceDepart, pDistance, pIndexDirection));
//        if (!roiEnEchec(pIndexDepart, index_arrivee(pIndexDepart, pPieceDepart, pDistance, pIndexDirection))) {
        System.out.print(Case.valeur(index_arrivee(pIndexDepart, pPieceDepart, pDistance, pIndexDirection)) +
                (pPrise ? "(capture)" : "") + ",");
//        }
    }

    private void afficher(int pIndexDepart, Piece pPieceDepart) {
        System.out.print(pPieceDepart.toString() + "(" + Case.valeur(pIndexDepart) + ") :");
    }

    private boolean case_existe(int pIndexDepart, Piece pPieceDepart, int pDistance, int pIndexDirection) {
        return index_arrivee(pIndexDepart, pPieceDepart, pDistance, pIndexDirection) != -1;
    }

    private boolean case_vide(int pIndexDepart, Piece pPieceDepart, int pDistance, int pIndexDirection) {
        return case_existe(pIndexDepart, pPieceDepart, pDistance, pIndexDirection) &&
                piece_arrivee(pIndexDepart, pPieceDepart, pDistance, pIndexDirection) == null;
    }

    private boolean case_nonvide(int pIndexDepart, Piece pPieceDepart, int pDistance, int pIndexDirection) {
        return case_existe(pIndexDepart, pPieceDepart, pDistance, pIndexDirection) &&
                piece_arrivee(pIndexDepart, pPieceDepart, pDistance, pIndexDirection) != null;
    }

    private boolean couleurs_opposees(int pIndexDepart, Piece pPieceDepart, int pDistance, int pIndexDirection) {
        return pPieceDepart.getCouleur() != piece_arrivee(pIndexDepart, pPieceDepart, pDistance, pIndexDirection).getCouleur();
    }

    private boolean estUnPionDepart(int pIndexDepart, Piece pPieceDepart) {
        return Case.valeur(pIndexDepart).estARangee2() && pPieceDepart.getCouleur() == Couleur.BLANC ||
                Case.valeur(pIndexDepart).estARangee7() && pPieceDepart.getCouleur() == Couleur.NOIR;
    }

    private Piece piece_arrivee(int pIndexDepart, Piece pPieceDepart, int pDistance, int pIndexDirection) {
        return PIECES[index_arrivee(pIndexDepart, pPieceDepart, pDistance, pIndexDirection)];
    }

    private int index_arrivee(int pIndexDepart, Piece pPieceDepart, int pDistance, int pIndexDirection) {
        return ECHIQUIER[TO_ECHIQUIER[pIndexDepart] + pDistance * pPieceDepart.getDeplacement()[pIndexDirection]];
    }

    private void traiter_ep() {
    }

    private void traiter_promotion() {
        System.out.print("promotion du pion");
    }

    public void initialiser(Couleur pCouleurQuiJoue) {
        _couleurQuiJoue = pCouleurQuiJoue;
        placer(TOUR_BLANCHE, a1);
        placer(CAVALIER_BLANC, b1);
        placer(FOU_BLANC, c1);
        placer(DAME_BLANCHE, d1);
        placer(ROI_BLANC, e1);
        placer(FOU_BLANC, f1);
        placer(CAVALIER_BLANC, g1);
        placer(TOUR_BLANCHE, h1);
        placer(PION_BLANC, a2);
        placer(PION_BLANC, b2);
        placer(PION_BLANC, c2);
        placer(PION_BLANC, d2);
        placer(PION_BLANC, e2);
        placer(PION_BLANC, f2);
        placer(PION_BLANC, g2);
        placer(PION_BLANC, h2);
        placer(PION_NOIR, a7);
        placer(PION_NOIR, b7);
        placer(PION_NOIR, c7);
        placer(PION_NOIR, d7);
        placer(PION_NOIR, e7);
        placer(PION_NOIR, f7);
        placer(PION_NOIR, g7);
        placer(PION_NOIR, h7);
        placer(TOUR_NOIRE, a8);
        placer(CAVALIER_NOIR, b8);
        placer(FOU_NOIR, c8);
        placer(DAME_NOIRE, d8);
        placer(ROI_NOIR, e8);
        placer(FOU_NOIR, f8);
        placer(CAVALIER_NOIR, g8);
        placer(TOUR_NOIRE, h8);

        traiter_0();
    }
}
     


